﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace CenyLetu
{
    /// <summary>
    /// Systém plánování událostí systému.
    /// </summary>
    class Planovac
    {
        /// <summary>
        /// Kolekce triggerů, které plánovač plánuje.
        /// </summary>
        private ICollection<ITrigger> triggery;
        /// <summary>
        /// Čas příštího spuštění.
        /// </summary>
        private DateTime pristiSpusteni;
        /// <summary>
        /// Ukončení cyklu vlákna.
        /// </summary>
        private bool stop;
        /// <summary>
        /// Pracovní vlákno plánovače.
        /// </summary>
        private Thread pracovniVlakno;


        /// <summary>
        /// Konstruktor
        /// </summary>
        public Planovac()
        {
            triggery = new List<ITrigger>();
            stop = false;
            pracovniVlakno = new Thread(Run);
        }

        /// <summary>
        /// Zaregistruje standardní triggery.
        /// </summary>
        public void ZaregistrujTriggery()
        {
            triggery.Add(new TriggerImportCen());
            // triggery.Add(new TriggerBI());
        }

        /// <summary>
        /// Spustí vlákno plánovače.
        /// </summary>
        public void SpustPlanovac()
        {
            if (pracovniVlakno.ThreadState != ThreadState.Unstarted)
                return;

            pracovniVlakno.Start();
        }

        /// <summary>
        /// Preruší plánovač.
        /// </summary>
        public void PrerusPlanovac()
        {
            pracovniVlakno.Interrupt();
        }

        /// <summary>
        /// Přeruší plánovač a vyčká na spojení vláken.
        /// </summary>
        public void UkonciPlanovacASpojVlakna()
        {
            PrerusPlanovac();
            pracovniVlakno.Join();
        }

        /// <summary>
        /// Pracovní metoda vlákna.
        /// </summary>
        public void Run()
        {
            while (!stop)
            {
                // zjisti čas přístího spuštění
                foreach (ITrigger item in triggery)
                {
                    DateTime spusteni = item.DejCasDalsihoSpusteni();
                    if (pristiSpusteni == default(DateTime) || spusteni < pristiSpusteni)
                        pristiSpusteni = spusteni;
                }

                // proveď uspání na čekací dobu
                if (pristiSpusteni > DateTime.Now)
                {
                    TimeSpan rozdil = pristiSpusteni - DateTime.Now;

                    try
                    {
                        Thread.Sleep(rozdil.TotalMinutes > 10 ? 10 * 60 * 1000 : (int)rozdil.TotalMilliseconds);
                    }
                    catch (ThreadInterruptedException)
                    {
                        stop = true;
                    }
                    continue;
                }

                // proveď triggery
                foreach (ITrigger item in triggery)
                {
                    if (item.DejCasDalsihoSpusteni() < DateTime.Now)
                        item.Proved();
                }

                pristiSpusteni = default(DateTime);
            }
        }

    }
}
